home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / address.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  7.7 KB  |  287 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 1
  2. #ifndef NeXT
  3. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  4. #pragma load EUDORA_LOAD
  5. #pragma segment Boxes
  6. #define PState(cc,rc,ss)
  7. #else
  8. typedef unsigned char **Handle,*UPtr,Byte;
  9. typedef Handle UHandle;
  10. typedef Byte Str255[256];
  11. #define nil ((void*)0)
  12. #define MEM_ERR 0
  13. #define ADDR_TOO_LONG 0
  14. #define BAD_ADDRESS 0
  15. #define WarnUser(a,b) puts(#a #b)
  16. #define Boolean int
  17. #define True 1
  18. #define False 0
  19. #define MemError() 0
  20. #include "address.h"
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. Handle NuHandle(long size)
  24. {
  25.     UPtr data=malloc(size);
  26.     Handle hand=malloc(2*sizeof(UPtr));
  27.     *hand = data;
  28.     hand[1] = (UPtr)size;
  29.     return(hand);
  30. }
  31. void SetHandleBig(Handle hand,int size)
  32. {
  33.     *hand = realloc(*hand,size);
  34.     hand[1] = (UPtr)size;
  35. }
  36. void DisposHandle(Handle hand)
  37. {
  38.     free(*hand);
  39.     free(hand);
  40. }
  41. int PtrAndHand(UPtr ptr,UHandle hand,int size)
  42. {
  43.     int oldSize = (int)hand[1];
  44.     SetHandleBig(hand,oldSize+size);
  45.     bcopy(ptr,*hand+oldSize,size);
  46.     return(0);
  47. }
  48. int verbose;
  49. #define LDRef(h) (*h)
  50. #define UL(h)
  51. #define IsWhite(c) (c==' ' || c=='\t')
  52. char *stateNames[]={"sNoChange","sPlain","sParen","sAngle","sBrak","sQuot",
  53. "sTrail","sTDone","sError","sToken","sBrakE","sQuotE","incPar","decPar"};
  54. char *classNames[]={"Regular","Comma","lParen","rParen","lAngle","rAngle",
  55. "lBrak","rBrak","dQuote","aDone"};
  56. #define PState(cc,rc,ss) do {*ap = 0; if (verbose && cc!=aDone) printf("%c: %8s %-10s {%s}\n",rc,classNames[cc],stateNames[1+ss],addressBuffer+1);} while(0)
  57. #endif
  58. typedef enum
  59. {
  60.     Regular, Comma, lParen, rParen, lAngle, rAngle,
  61.     lBrak, rBrak, dQuote, aDone
  62. } AddressCharEnum;
  63. typedef enum
  64. {
  65.     sNoChange= -1,/* remain in current state */
  66.     sPlain,             /* nothing special going on */
  67.     sParen,             /* within parentheses */
  68.     sAngle,             /* within angle brackets */
  69.     sBrak,                /* within square brackets */
  70.     sQuot,                /* with double quotes */
  71.     sTrail,             /* trailer after an angle bracket */
  72.     sTDone,             /* the token is done for this address */
  73. /* the following are states that decay immediately into other states */
  74.     sError,             /* bad address; causes routine to punt */
  75.     sToken,             /* process completed token (sPlain) */
  76.     sBrakE,             /* close [] (pushed state (sPlain,sAngle,sTDone)) */
  77.     sQuotE,             /* close "" (pushed state (sPlain,sAngle,sTDone)) */
  78.     incPar,             /* increment () level (sParen) */
  79.     decPar,             /* decrement () level (sParen or pushed state) */
  80.     sTrailB             /* beginning of trailer state */
  81. } AddressStateEnum;
  82. char AddrStateTable[sTDone+1][aDone+1] = {
  83. /*                            .             ,             (             )             <             >             [             ]             "       aDone*/
  84. /* sPlain */        -1,         sToken, incPar, sError, sAngle, sError, sBrak,    sError, sQuot,    sToken,
  85. /* sParen */        -1,         -1,         incPar, decPar, -1,         -1,         -1,         -1,         -1,         sError,
  86. /* sAngle */        -1,         -1,         incPar, decPar, sError, sTrailB, sBrak, sError, sQuot,    sError,
  87. /* sBrak */         -1,         -1,         -1,         -1,         -1,         -1,         sError, sBrakE, -1,         sError,
  88. /* sQuot */         -1,         -1,         -1,         -1,         -1,         -1,         -1,         -1,         sQuotE, sError,
  89. /* sTrail */        -1,         sToken, incPar, decPar, sError, sError, -1,         -1,         -1,         sToken,
  90. /* sTDone */        -1,         sToken, incPar, sError, sAngle, sError, sBrak,    sError, sQuot,    sToken
  91. };
  92. /************************************************************************
  93.  * SuckAddresses - parse the RFC 822 Address format
  94.  * Returns a handle to some storage of the form:
  95.  *            [<length byte>address<nil>]...<nil> 
  96.  ************************************************************************/
  97. UHandle  SuckAddresses(UHandle    text,long size,Boolean wantComments)
  98. {
  99.     UHandle  res;
  100.     res = SuckPtrAddresses(LDRef(text),size,wantComments);
  101.     UL(text);
  102.     return(res);
  103. }
  104.  
  105. UHandle  SuckPtrAddresses(UPtr text,long size,Boolean wantComments)
  106. {
  107.     UHandle  newAddresses;
  108.     UPtr spot;
  109.     short paren=0;
  110.     short count=0;
  111.     char oldState, state, nextState;
  112.     Byte c, cClass;
  113.     Str255 addressBuffer;
  114.     UPtr ap;
  115. #define AddrFull                (ap-addressBuffer >= sizeof(addressBuffer)-2)
  116. #define AddrEmpty             (ap==addressBuffer+1)
  117. #define AddrChar(c)         do {if ((wantComments||!IsWhite(c)) && oldState!=sTDone) *ap++ = c;} while (0)
  118. #define CmmntChar(c)        do {if (wantComments && oldState!=sTDone) *ap++ = c;} while (0)
  119. #define AddrAny(c)            do {if (oldState!=sTDone) *ap++ = c;} while (0)
  120. #define RestartAddr()     ap=addressBuffer+1
  121.     newAddresses = NuHandle(0L);
  122.     if (newAddresses==nil) {WarnUser(MEM_ERR,MemError()); return(nil);}
  123.     
  124.     oldState = state = sPlain;
  125.     for (spot=text;(spot<text+size) && (IsWhite(*spot));spot++);
  126.     RestartAddr();
  127.     do
  128.     {
  129.         if (spot >= text + size)
  130.             cClass = aDone;
  131.         else
  132.         {
  133.             switch (c = *spot++)
  134.             {
  135.                 case ',':             cClass = Comma; break;
  136.                 case '(':             cClass = lParen; break;
  137.                 case ')':             cClass = rParen; break;
  138.                 case '[':             cClass = lBrak; break;
  139.                 case ']':             cClass = rBrak; break;
  140.                 case '<':             cClass = lAngle; break;
  141.                 case '>':             cClass = rAngle; break;
  142.                 case '"':       cClass = dQuote; break;
  143.                 default:                cClass = Regular; break;
  144.             }
  145.         }
  146.         nextState = AddrStateTable[state][cClass];
  147.         PState(cClass,spot[-1],nextState);
  148.         if (nextState == sNoChange) nextState = state;
  149.         switch (nextState)
  150.         {
  151.             case sPlain:
  152.                 AddrChar(c);
  153.                 break;
  154.             case sAngle:
  155.                 if (state==sAngle || wantComments)
  156.                     AddrChar(c);
  157.                 else
  158.                     RestartAddr();
  159.                 break;
  160.             case sBrak:
  161.                 if (state!=sBrak)
  162.                     oldState = state;
  163.                 AddrAny(c);
  164.                 break;
  165.             case sQuot:
  166.                 if (state!=sQuot) oldState = state;
  167.                 AddrAny(c);
  168.                 break;
  169.             case sTDone:
  170.                 break;
  171.             case sError:
  172.                 count = 0;
  173.                 goto parsePunt;
  174.                 break;
  175.             case sToken:
  176.                 while (!AddrEmpty && IsWhite(ap[-1])) ap--; /* strip trailing space */
  177.                 *ap++ = '\0';
  178.                 if (addressBuffer[1])
  179.                 {
  180.                     *addressBuffer = ap-addressBuffer - 2;
  181.                     if (PtrAndHand(addressBuffer,newAddresses,*addressBuffer+2))
  182.                     {
  183.                         int err = MemError();
  184.                         SetHandleBig(newAddresses,0L);
  185.                         WarnUser(MEM_ERR,err);
  186.                         count = 0;
  187.                         goto parsePunt;
  188.                     }
  189.                     else
  190.                         count++;
  191.                 }
  192.                 RestartAddr();
  193.                 nextState = oldState = sPlain;
  194.                 PState(cClass,' ',nextState);
  195.                 while ((spot<text+size) && (IsWhite(*spot))) spot++;
  196.                 break;
  197.             case sTrailB:
  198.                 nextState = sTrail;
  199.                 CmmntChar('>');
  200.                 break;
  201.             case sBrakE:
  202.                 nextState = oldState;
  203.                 PState(cClass,' ',nextState);
  204.                 AddrChar(c);
  205.                 break;
  206.             case sQuotE:
  207.                 nextState = oldState;
  208.                 PState(cClass,' ',nextState);
  209.                 AddrChar(c);
  210.                 break;
  211.             case incPar:
  212.                 if (!paren++) oldState=state;
  213.                 nextState = sParen;
  214.                 PState(cClass,' ',nextState);
  215.                 CmmntChar('(');
  216.                 break;
  217.             case decPar:
  218.                 if (!--paren)
  219.                     nextState = oldState;
  220.                 else
  221.                     nextState = sParen;
  222.                 PState(cClass,' ',nextState);
  223.                 CmmntChar(')');
  224.                 break;
  225.             default:
  226.                 CmmntChar(c);
  227.                 break;
  228.         }
  229.         state = nextState;
  230.     }
  231.     while (cClass!=aDone && !AddrFull);
  232.     if (PtrAndHand("",newAddresses,1))
  233.     {
  234.         int err = MemError();
  235.         SetHandleBig(newAddresses,0L);
  236.         WarnUser(MEM_ERR,err);
  237.     }
  238. parsePunt:    
  239.     if ((nextState==sError)||AddrFull)
  240.     {
  241.         DisposHandle(newAddresses);
  242.         if (AddrFull) WarnUser(ADDR_TOO_LONG,0);
  243.         else if (nextState==sError) WarnUser(BAD_ADDRESS,0);
  244.         return(nil);
  245.     }
  246.     else
  247.         return(newAddresses);
  248. }
  249.  
  250. #ifdef NeXT
  251. main(int argc,unsigned char **argv)
  252. {
  253.     Str255 addr;
  254.     if (argc>1) verbose=1;
  255.     while(gets((char *)addr))
  256.     {
  257.         UHandle  h;
  258.         UPtr p;
  259.         
  260.         printf("Address: {%s}",addr);
  261.         putchar(verbose ? '\n' : ' ');
  262.         h = SuckPtrAddresses(addr,strlen(addr),False);
  263.         if (!h) fputs("{nil}",stdout);
  264.         else
  265.         {
  266.             if (!**h) fputs("{empty}",stdout);
  267.             else
  268.                 for (p=*h;*p;p+=*p+2)
  269.                     printf("%s{%s}",p==*h?"":", ",p+1);
  270.             DisposHandle(h);
  271.         }
  272.         putchar(verbose ? '\n' : ' ');
  273.         h = SuckPtrAddresses(addr,strlen(addr),True);
  274.         if (!h) fputs("{nil}",stdout);
  275.         else
  276.         {
  277.             if (!**h) fputs("{empty}",stdout);
  278.             else
  279.                 for (p=*h;*p;p+=*p+2)
  280.                     printf("%s{%s}",p==*h?"":", ",p+1);
  281.             DisposHandle(h);
  282.         }
  283.         putchar('\n');
  284.     }
  285. }
  286. #endif
  287.